// AttachProcessDlg.cpp : implementation file
//

#include "stdafx.h"
#include "MemMapView.h"
#include "AttachProcessDlg.h"

// CAttachProcessDlg dialog

IMPLEMENT_DYNAMIC(CAttachProcessDlg, CDialog)

CAttachProcessDlg::CAttachProcessDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CAttachProcessDlg::IDD, pParent)
{

}

CAttachProcessDlg::~CAttachProcessDlg()
{
}

void CAttachProcessDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_PROCESSLIST, m_ProcessList);
	DDX_Control(pDX, IDOK, m_OK);
}


BEGIN_MESSAGE_MAP(CAttachProcessDlg, CDialog)
	ON_NOTIFY(LVN_ITEMCHANGED, IDC_PROCESSLIST, &CAttachProcessDlg::OnLvnItemchangedProcesslist)
	ON_BN_CLICKED(IDC_SHOWSYSTEM, &CAttachProcessDlg::OnBnClickedShowsystem)
	ON_NOTIFY(NM_DBLCLK, IDC_PROCESSLIST, &CAttachProcessDlg::OnNMDblclkProcesslist)
	ON_BN_CLICKED(IDC_REFRESH, &CAttachProcessDlg::OnBnClickedRefresh)
END_MESSAGE_MAP()


// CAttachProcessDlg message handlers

BOOL CAttachProcessDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	m_ProcessList.EnableMarkSortedColumn();
	m_ProcessList.SetExtendedStyle(LVS_EX_FULLROWSELECT);

	m_ProcessList.InsertColumn(0, _T("Name"), LVCFMT_LEFT, 160);
	m_ProcessList.InsertColumn(1, _T("ID"), LVCFMT_RIGHT, 100);

	InitProcesses(false);
	return TRUE;
}

void CAttachProcessDlg::InitProcesses(bool include_system) {
	const CProcessList::ProcessList& processes = m_ProcessListBuilder.Create();
	CString str;
	m_ProcessList.DeleteAllItems();

	for(POSITION pos = processes.GetHeadPosition(); pos; ) {
		const PROCESSENTRY32* pe = processes.GetNext(pos);
		if(!include_system && m_ProcessListBuilder.IsSystem(pe->th32ProcessID)) continue;

		bool iswow = false;
#ifdef _WIN64
		iswow = CProcessList::IsWow64Process(pe->th32ProcessID);
#endif
		str.Format(_T("%s%s"), pe->szExeFile, iswow ? _T(" *32") : _T(""));
		int n = m_ProcessList.InsertItem(m_ProcessList.GetItemCount(), str);
		str.Format(_T("%d (0x%X)"), pe->th32ProcessID, pe->th32ProcessID);
		m_ProcessList.SetItemText(n, 1, str);
		m_ProcessList.SetItemData(n, (DWORD_PTR)pe);
	}
}

int CAttachProcessDlg::CProcessListCtrl::OnCompareItems(LPARAM p1, LPARAM p2, int col) {
	PROCESSENTRY32* pe1 = (PROCESSENTRY32*)p1, *pe2 = (PROCESSENTRY32*)p2;
	switch(col) {
		case 0:	// EXE name
			return ::lstrcmpi(pe1->szExeFile, pe2->szExeFile);
		case 1:	// PID
			return pe1->th32ProcessID > pe2->th32ProcessID ? 1 : -1;
	}
	return 0;
}

void CAttachProcessDlg::OnLvnItemchangedProcesslist(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	
	m_OK.EnableWindow(m_ProcessList.GetSelectedCount() > 0);

	*pResult = 0;
}

void CAttachProcessDlg::OnOK()
{
	POSITION pos = m_ProcessList.GetFirstSelectedItemPosition();
	PROCESSENTRY32* info = (PROCESSENTRY32*)m_ProcessList.GetItemData(m_ProcessList.GetNextSelectedItem(pos)); 
	m_SelectedProcessID = info->th32ProcessID;
	m_ProcessInfo = *info;

	CDialog::OnOK();
}

void CAttachProcessDlg::OnBnClickedShowsystem()
{
	InitProcesses(IsDlgButtonChecked(IDC_SHOWSYSTEM) == BST_CHECKED ? true : false);
}

void CAttachProcessDlg::OnNMDblclkProcesslist(NMHDR *pNMHDR, LRESULT *pResult)
{
	LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
	POSITION pos = m_ProcessList.GetFirstSelectedItemPosition();
	if(pos)
		OnOK();

	*pResult = 0;
}

void CAttachProcessDlg::OnBnClickedRefresh() {
	InitProcesses(IsDlgButtonChecked(IDC_SHOWSYSTEM) == BST_CHECKED ? true : false);
}
